package net.tools.web;

import java.io.*;
import java.math.*;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;

public class TunnelServlet extends HttpServlet
{

	private static final String APPLICATION_PROCESSOR_KEY = "jspsocks5.applicationProcessor";

	public void init() throws ServletException
	{
		new File(getServletContext().getRealPath("/WEB-INF/rsakeys")).mkdir();
		File fprikey = new File(getServletContext().getRealPath("/WEB-INF/rsakeys/privatekey.properties"));
		if(!fprikey.exists())
		{
			try
			{
				KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
				kpg.initialize(2048);
				KeyPair kp = kpg.generateKeyPair();
				RSAPublicKey pubkey = (RSAPublicKey) kp.getPublic();
				RSAPrivateKey prikey = (RSAPrivateKey) kp.getPrivate();
				Properties pubkeyprops = new Properties();
				Properties prikeyprops = new Properties();
				pubkeyprops.setProperty("jspsocks5.publickey.modulus", pubkey.getModulus().toString());
				pubkeyprops.setProperty("jspsocks5.publickey.publicExponent", pubkey.getPublicExponent().toString());
				prikeyprops.setProperty("jspsocks5.privatekey.modulus", prikey.getModulus().toString());
				prikeyprops.setProperty("jspsocks5.privatekey.privateExponent", prikey.getPrivateExponent().toString());
				FileOutputStream pubkeyout = new FileOutputStream(getServletContext().getRealPath("/WEB-INF/rsakeys/publickey.properties"));
				pubkeyprops.store(pubkeyout, "jspsocks5.publickey");
				pubkeyout.flush();
				pubkeyout.close();
				pubkeyout = new FileOutputStream(getServletContext().getRealPath("/WEB-INF/publickey.txt"));
				pubkeyprops.store(pubkeyout, "jspsocks5.publickey");
				pubkeyout.flush();
				pubkeyout.close();
				FileOutputStream prikeyout = new FileOutputStream(fprikey);
				prikeyprops.store(prikeyout, "jspsocks5.privatekey");
				prikeyout.flush();
				prikeyout.close();
			}
			catch (NoSuchAlgorithmException e)
			{
				e.printStackTrace();
				throw new ServletException(e);
			}
			catch (FileNotFoundException e)
			{
				e.printStackTrace();
				throw new ServletException(e);
			}
			catch (IOException e)
			{
				e.printStackTrace();
				throw new ServletException(e);
			}
		}
		try
		{
			FileInputStream prikeyin = new FileInputStream(fprikey);
			Properties prikeyprops = new Properties();
			prikeyprops.load(prikeyin);
			prikeyin.close();
			ApplicationProcessor appProc = new ApplicationProcessor(new BigInteger(prikeyprops.getProperty("jspsocks5.privatekey.modulus")), new BigInteger(prikeyprops.getProperty("jspsocks5.privatekey.privateExponent")));
			getServletContext().setAttribute(APPLICATION_PROCESSOR_KEY, appProc);
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
			throw new ServletException(e);
		}
		catch (IOException e)
		{
			e.printStackTrace();
			throw new ServletException(e);
		}
		catch (NoSuchAlgorithmException e)
		{
			e.printStackTrace();
			throw new ServletException(e);
		}
		catch (InvalidKeySpecException e)
		{
			e.printStackTrace();
			throw new ServletException(e);
		}
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException
	{
		final String SESSION_PROCESSOR_KEY = "jspsocks5.sessionProcessor";
		HttpSession sess = req.getSession();
		SessionProcessor sessProc = (SessionProcessor) sess.getAttribute(SESSION_PROCESSOR_KEY);
		try
		{
			if(sessProc != null)
				sessProc.processCommand(req.getInputStream(), resp.getOutputStream());
			else
			{
				ApplicationProcessor appProc = (ApplicationProcessor) getServletContext().getAttribute(APPLICATION_PROCESSOR_KEY);
				sess.setAttribute(SESSION_PROCESSOR_KEY, appProc.startSession(req.getInputStream(), resp.getOutputStream()));
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

}
